package cn.lbd.nonblockingnio;

import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Iterator;

public class Server implements Runnable {
    private Selector selector;
    private ByteBuffer readBuffer = ByteBuffer.allocate(1024);
    private ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
    private int rowCount;

    public Server(int port) {
        try {
            this.selector = Selector.open();
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.configureBlocking(false);
            serverSocketChannel.bind(new InetSocketAddress(port));
            serverSocketChannel.register(this.selector, SelectionKey.OP_ACCEPT);
            System.out.println("开始监听客户端，端口为" + port);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        //持续监听
        try {
            while (selector.select() > 0) {
                Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
                while (keys.hasNext()) {
                    SelectionKey key = keys.next();
                    dispatch(key);
                }
                keys.remove();
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public void dispatch(SelectionKey key) {
        if (key.isValid()) {
            if (key.isAcceptable()) {
                this.accept(key);
            }
            if (key.isReadable()) {
                this.read(key);
            }
        }
    }

    public void read(SelectionKey key) {
        SocketChannel socketChannel = null;
        String request = null;
        try {
            socketChannel = (SocketChannel) key.channel();
            int count = socketChannel.read(readBuffer);
            if (count == -1) {
                key.channel().close();
                key.cancel();
                return;
            }
            readBuffer.flip();
            byte[] bytes = new byte[readBuffer.limit()];
            readBuffer.get(bytes);
            request = new String(bytes).trim();

            if (++rowCount % 2 == 0) {
                System.out.println("                       " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + "\n" + "                                         " + request);
            } else {
                System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + "\n" + request);
            }

            readBuffer.clear();

            writeBuffer.put(("服务端收到客户端请求，请求信息为：" + request).getBytes());
            writeBuffer.flip();
            socketChannel.write(writeBuffer);
            writeBuffer.clear();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void accept(SelectionKey key) {
        ServerSocketChannel serverSocketChannel = null;
        try {
            serverSocketChannel = (ServerSocketChannel) key.channel();
            SocketChannel socketChannel = serverSocketChannel.accept();
            socketChannel.configureBlocking(false);
            socketChannel.register(this.selector, SelectionKey.OP_READ);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new Thread(new Server(8010)).start();
    }
}
